package com.chinafree.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chinafree.auth.model.enumeration.Column;
import com.chinafree.business.mapping.UserMapping;
import com.chinafree.business.model.enumeration.SalaryEnum;
import com.chinafree.business.model.param.JobParam;
import com.chinafree.business.model.queryCondition.JobQueryCondition;
import com.chinafree.business.model.result.JobResult;
import com.chinafree.business.model.result.UserBaseMessageResult;
import com.chinafree.business.model.result.UserEducationResult;
import com.chinafree.business.model.result.UserWorkResult;
import com.chinafree.business.model.result.BaseUserResult;
import com.chinafree.business.service.CompanyService;
import com.chinafree.business.service.JobService;
import com.chinafree.business.service.ResumeService;
import com.chinafree.business.service.UserService;
import com.chinafree.common.model.enumeration.ResponseCodeEnum;
import com.chinafree.common.model.response.ListPagingResponse;
import com.chinafree.mapper.MaJobMapper;
import com.chinafree.model.po.FndPosition;
import com.chinafree.model.po.MaJob;
import com.google.common.collect.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ScanIteration;
import org.springframework.stereotype.Service;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.util.Version;

import java.io.IOException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class JobServiceImpl extends BaseServiceImpl implements JobService {

    @Autowired
    private MaJobMapper maJobMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private CompanyService companyService;

    @Autowired
    private ResumeService resumeService;

    @Override
    public List<JobResult> getJobInfo() {
        QueryWrapper<MaJob> maJobQueryWrapper = new QueryWrapper<>();
        maJobQueryWrapper.eq(Column.COMPANY_ID.getColumn(), getCompanyId());
        List<MaJob> maJobs = maJobMapper.selectList(maJobQueryWrapper);
        List<JobResult> collect = maJobs.stream().map(this::getJobResult).collect(Collectors.toList());
        return collect;
    }

    @Override
    public JobResult getJobInfoById(Long body) {
        MaJob maJob = maJobMapper.selectById(body);
        JobResult jobResult = getJobResult(maJob);
        return jobResult;
    }

    @Override
    public void delete(Long body) {
        maJobMapper.deleteById(body);
    }

    private JobResult getJobResult(MaJob maJob) {
        if (maJob == null) {
            return null;
        }
        JobResult jobResult = UserMapping.instance.maJobToResult(maJob);

        jobResult.setId(maJob.getId());
        FndPosition jobTypeById = userService.getJobTypeById(jobResult.getJobType());
        if (jobTypeById != null) {
            jobResult.setJobTypeName(jobTypeById.getPositionName());
            jobResult.setJobTypeArray(Lists.newArrayList(jobTypeById.getType(), jobResult.getJobType()));
        }
        jobResult.setCompanyResult(companyService.getCompanyInfo(maJob.getCompanyId()));

        return jobResult;
    }

    @Override
    public void update(JobParam body) {
        MaJob maJob = UserMapping.instance.jobParamToMaJob(body);
        int i = maJobMapper.updateById(maJob);
    }

    @Override
    public void insert(JobParam body) {
        MaJob maJob = UserMapping.instance.jobParamToMaJob(body);
        maJob.setCompanyId(getCompanyId());
        int i = maJobMapper.insert(maJob);
    }

    @Override
    public ListPagingResponse<JobResult> queryUserPage(JobQueryCondition condition) {
        Page<MaJob> page = new Page<>(condition.getPageIndex(), condition.getPageSize());
        if (condition.getSortBy() == null || condition.getSortBy() == 1) {

            MaJob maJob = new MaJob();
            BeanUtils.copyProperties(condition, maJob);
            QueryWrapper<MaJob> entityWrapper = new QueryWrapper<>(maJob);
            if (condition.getJobNameM() != null) {
                entityWrapper.like("job_name", "%" + condition.getJobNameM() + "%");
            }
            entityWrapper.orderByDesc(Column.CREATE_TIME.getColumn());
            Page<MaJob> maJobPage = maJobMapper.selectPage(page, entityWrapper);
            List<JobResult> collect = maJobPage.getRecords().stream().map(this::getJobResult)
                    .collect(Collectors.toList());

            return new ListPagingResponse<>(ResponseCodeEnum.SUCCESS, "查询成功", collect, maJobPage.getCurrent(),
                    collect.size(), maJobPage.getTotal());
        }

        // Long userId = getUserId();
        UserBaseMessageResult userbaseResult = resumeService.getByUserId(getUserId()).getResponseData();
        MaJob maJob = new MaJob();
        BaseUserResult baseUserResult = userbaseResult.getBaseUserResult();
        if (baseUserResult == null) {
            return null;
        }
        int score = 0;
        if (baseUserResult.getLiveCity() != null) {
            maJob.setCityId(baseUserResult.getLiveCity());
        }
        if (baseUserResult.getJobType() != null) {
            maJob.setJobType(baseUserResult.getJobType());

        }
        List<UserEducationResult> userEducationResult = userbaseResult.getUserEducationResult();

        if (userEducationResult != null || userEducationResult.size() > 0) {
            int degree = 0;
            for (UserEducationResult uResult : userEducationResult) {
                degree = uResult.getDegree() > degree ? uResult.getDegree() : degree;
            }
            maJob.setDegreeId(degree);

        }
        List<UserWorkResult> userWorkResult = userbaseResult.getUserWorkResult();
        if (userWorkResult != null || userWorkResult.size() > 0) {
            Long day = 0L;
            for (UserWorkResult uWorkResult : userWorkResult) {
                Long days = 0L;
                if (uWorkResult.getStartTime() != null && uWorkResult.getEndTime() != null) {
                    Duration duration = Duration.between(uWorkResult.getStartTime(), uWorkResult.getEndTime());
                    days = duration.toDays();
                }
                day = day + days;
            }
            Integer workResult1 = SalaryEnum.getSalaryIdByDay(day);
            maJob.setQualification(workResult1);

        }
        Page<MaJob> maJobPage = maJobMapper.selectPage(page, new QueryWrapper<MaJob>(maJob));

        List<JobResult> collect = maJobPage.getRecords().stream().map(u -> getJobResult1(u, userbaseResult))
                .sorted(Comparator.comparing(JobResult::getScore).reversed())
                .collect(Collectors.toList());

        return new ListPagingResponse<>(ResponseCodeEnum.SUCCESS, "查询成功", collect, maJobPage.getCurrent(),
                collect.size(), maJobPage.getTotal());
    }

    private JobResult getJobResult1(MaJob maJob, UserBaseMessageResult userbaseResult) {
        if (maJob == null) {
            return null;
        }
        JobResult jobResult = UserMapping.instance.maJobToResult(maJob);

        jobResult.setId(maJob.getId());
        FndPosition jobTypeById = userService.getJobTypeById(jobResult.getJobType());
        if (jobTypeById != null) {
            jobResult.setJobTypeName(jobTypeById.getPositionName());
            jobResult.setJobTypeArray(Lists.newArrayList(jobTypeById.getType(), jobResult.getJobType()));
        }
        jobResult.setCompanyResult(companyService.getCompanyInfo(maJob.getCompanyId()));

        // 计算分数
        Double score = 0.0;
        BaseUserResult baseUserResult = userbaseResult.getBaseUserResult();
        if (baseUserResult.getLiveCity() != null && jobResult.getCityId() != null) {
            score += baseUserResult.getLiveCity().equals(jobResult.getCityId()) ? 20 : 0;
        }
        // 工作类型
        if (baseUserResult.getJobType() != null && jobResult.getJobType() != null) {
            score += baseUserResult.getJobType().equals(  jobResult.getJobType()) ? 15 : 0;
        }
        List<UserEducationResult> userEducationResult = userbaseResult.getUserEducationResult();
        if (userEducationResult != null || userEducationResult.size() > 0 && jobResult.getDegreeId() != null) {
            int degree = 0;
            for (UserEducationResult uResult : userEducationResult) {
                degree = uResult.getDegree() > degree ? uResult.getDegree() : degree;
            }
            score += jobResult.getDegreeId().equals( degree) ? 15 : (
                jobResult.getDegreeId()<degree?  1-(jobResult.getDegreeId()-degree)/5:0
            );
            
        }
        List<UserWorkResult> userWorkResult = userbaseResult.getUserWorkResult();
        if (userWorkResult != null || userWorkResult.size() > 0 && jobResult.getQualification() != null) {
            Long day = 0L;
            for (UserWorkResult uWorkResult : userWorkResult) {
                Long days = 0L;
                if (uWorkResult.getStartTime() != null && uWorkResult.getEndTime() != null) {
                    Duration duration = Duration.between(uWorkResult.getStartTime(), uWorkResult.getEndTime());
                    days = duration.toDays();
                }
                day = day + days;
            }
            Integer workResult1 = SalaryEnum.getSalaryIdByDay(day);
            score += workResult1 == jobResult.getQualification() ? 10 : 0;
        }

        // 薪水

        Integer userStart = baseUserResult.getSalaryStart();
        Integer userEnd = baseUserResult.getSalaryEnd();
        Integer jobStart = jobResult.getSalaryStart();
        Integer jobEnd = jobResult.getSalaryEnd();
        if (userStart != null && userEnd != null && jobStart != null && jobEnd != null) {
            double max = (double) (Math.max(userEnd, jobEnd) - Math.min(userStart, jobStart));

            if (jobStart < userStart) {
               if (jobEnd >= userStart && jobEnd <= userEnd) {
                    score += (userEnd - jobEnd) / max * 10;
                } else if (jobEnd > userEnd) {
                    score += 10;
                }
            } else if (jobStart >= userStart && jobStart <= userEnd) {
                if (jobEnd >= userStart && jobEnd <= userEnd) {
                    score +=((jobStart-userStart)+(userEnd - jobEnd))/max *10;
                } else if (jobEnd > userEnd) {
                    score +=((jobStart-userStart))/max*10;
                }
            }

        }
        score += twoWayMatch(baseUserResult.getSummary(), jobResult.getJobRequired() + jobResult.getJobResponsibility())
                * 30;
              
                
        jobResult.setScore(String .format("%.2f",score));

        return jobResult;

    }

    public double twoWayMatch(String text1, String text2) {
        return (oneWayMatch(text1, text2) + oneWayMatch(text2, text1))/2;
    }

    private static SmartChineseAnalyzer smartChineseAnalyzer = new SmartChineseAnalyzer();

    private static List<String> smallWeightWords = Arrays.asList("技术", "股份");

    private static double smallWeight = 0.3D;

    public double oneWayMatch(String text1, String text2) {
        try {
            Set<String> set = new HashSet<String>(10);
            TokenStream tokenStream = smartChineseAnalyzer.tokenStream("field", text1);
            CharTermAttribute charTermAttribute = tokenStream.getAttribute(CharTermAttribute.class);
            tokenStream.reset();
            while (tokenStream.incrementToken()) {
                set.add(charTermAttribute.toString());
            }
            int originalCount = set.size();//
            tokenStream.end();
            tokenStream.close();
            tokenStream = smartChineseAnalyzer.tokenStream("field", text2);
            charTermAttribute = tokenStream.getAttribute(CharTermAttribute.class);
            tokenStream.reset();
            int smallWeightWordsCount = 0;
            int denominator = 0;//
            while (tokenStream.incrementToken()) {
                denominator++;//
                String word = charTermAttribute.toString();
                int tempSize = set.size();
                set.add(word);
                if (tempSize + 1 == set.size() && smallWeightWords.contains(word)) {
                    smallWeightWordsCount++;
                }
            }
            int numerator = set.size() - originalCount;
            double unmatchRate = (smallWeightWordsCount * smallWeight + numerator - ((double) smallWeightWordsCount))
                    / denominator;//
            tokenStream.end();
            tokenStream.close();
            return unmatchRate;
        } catch (IOException e) {

            return 1D;
        }
    }

}
